﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Xaml.Shapes;

// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236

namespace Daphne.ControlsMetro.Clock
{
    /// <summary>
    /// Control representing one digital number
    /// </summary>
    public sealed partial class DigitalNumber : UserControl
    {
        /// <summary>
        /// Brush representing the foreground when digital number item is switched on
        /// </summary>
        public static readonly DependencyProperty ForegroundOnProperty;

        /// <summary>
        /// The number to display in the control
        /// </summary>
        public static readonly DependencyProperty NumberProperty;

        /// <summary>
        /// Registers the new dependency properties
        /// </summary>
        static DigitalNumber()
        {
            ForegroundOnProperty = DependencyProperty.Register("ForegroundOn", 
                                        typeof(Brush), typeof(DigitalNumber),
                                        new PropertyMetadata(null));
            
            NumberProperty = DependencyProperty.Register("Number",
                                                typeof(int), typeof(DigitalNumber),
                                                new PropertyMetadata(0, OnNumberChanged));
        }

        /// <summary>
        /// Thickness and radius factor 
        /// </summary>
        private const double _thicknessFactor = 0.15d;
        private const double _radiusFactor = 1d / 3d;

        /// <summary>
        /// The list of digital number items
        /// </summary>
        private List<Border> _numberItems;

        /// <summary>
        /// Constructor
        /// </summary>
        public DigitalNumber()
        {
            // init
            this.InitializeComponent();
            _numberItems = new List<Border>();

            // create loaded event for setting up the control
            this.Loaded += DigitalNumber_Loaded;            
        }

        /// <summary>
        /// Event for setting up the number
        /// </summary>
        void DigitalNumber_Loaded(object sender, RoutedEventArgs e)
        {
            // create the control internals
            BuildControl();

            // show the set number
            UpdateNumberVisual();
        }

        #region CLR Wrappers for dependency properties

        /// <summary>
        /// Visible foreground brush
        /// </summary>
        public Brush ForegroundOn
        {
            get
            {
                return (Brush)GetValue(ForegroundOnProperty);
            }
            set
            {
                SetValue(ForegroundOnProperty, value);
            }
        }

        /// <summary>
        /// The number to show on digital-number control
        /// </summary>
        public int Number
        {
            get
            {
                return (int)GetValue(NumberProperty);
            }
            set
            {
                SetValue(NumberProperty, value);
            }       
        }

        /// <summary>
        /// Handler notifying the change in the visual appearance of the control
        /// </summary>
        static void OnNumberChanged(DependencyObject depObject, DependencyPropertyChangedEventArgs args)
        {
            (depObject as DigitalNumber).UpdateNumberVisual();
        }

        #endregion

        /// <summary>
        /// Internal method for building the digital number control
        /// </summary>
        private void BuildControl()
        {
            // calculate item thickness
            double thickness = uxCanvas.Width * _thicknessFactor;
            double radius = thickness * _radiusFactor;
            double length = uxCanvas.Width - 2 * thickness;
            uxCanvas.Height = thickness * 3 + length * 2;

             // create horizontal items
            /////////////////////////////////////

            double left = thickness;
            double top = 0;
            CreateRectangleItem(left, top, length, thickness, radius);

            top += thickness + length;
            CreateRectangleItem(left, top, length, thickness, radius);

            top += thickness + length;
            CreateRectangleItem(left, top, length, thickness, radius);

             // create vertical items
            ///////////////////////////////////////

            left = 0;
            top = thickness;
            CreateRectangleItem(left, top, thickness, length, radius);

            top += thickness + length;
            CreateRectangleItem(left, top, thickness, length, radius);

            left = thickness + length;
            top = thickness;
            CreateRectangleItem(left, top, thickness, length, radius);

            top += thickness + length;
            CreateRectangleItem(left, top, thickness, length, radius);
        }

        /// <summary>
        /// Creates and places rectangle item
        /// </summary>
        private void CreateRectangleItem(double left, double top, double width, double height, double radius)
        {
            // create item
            Border rect = new Border();

            // set position and size
            Canvas.SetLeft(rect, left);
            Canvas.SetTop(rect, top);
            rect.Width = width;
            rect.Height = height;
            rect.CornerRadius = new CornerRadius(radius);

            // set color
            rect.Background =  Foreground;

            // add to the containers
            uxCanvas.Children.Add(rect);
            _numberItems.Add(rect);
        }
   

        /// <summary>
        /// Updates the visual number
        /// </summary>
        private void UpdateNumberVisual()
        {
            if (_numberItems.Count == 0)
                return;

            // get the number digital visual record
            List<bool> digitalRec;
            if (_digitalNumberVisual.TryGetValue(Number, out digitalRec) == false)
                throw new ArgumentOutOfRangeException("Number");

            // set the visual number appearance
            for(int i = 0; i < digitalRec.Count; i++)
            {
                Border rect = _numberItems[i];
                Binding binding = new Binding();
                binding.Source = this;
                binding.Path = digitalRec[i] ? new PropertyPath("ForegroundOn") : new PropertyPath("Foreground");
                rect.SetBinding(Border.BackgroundProperty, binding);
            }
        }

        /// <summary>
        /// Digital Number Visual Records
        /// </summary>
        private Dictionary<int, List<bool>> _digitalNumberVisual = new Dictionary<int, List<bool>>()
        {
            {0, new List<bool>() {true, false, true, true, true, true, true}},
            {1, new List<bool>() {false, false, false, false, false, true, true}},
            {2, new List<bool>() {true, true, true, false, true, true, false}},
            {3, new List<bool>() {true, true, true, false, false, true, true}},
            {4, new List<bool>() {false, true, false, true, false, true, true}},
            {5, new List<bool>() {true, true, true, true, false, false, true}},
            {6, new List<bool>() {true, true, true, true, true, false, true}},
            {7, new List<bool>() {true, false, false, false, false, true, true}},
            {8, new List<bool>() {true, true, true, true, true, true, true}},
            {9, new List<bool>() {true, true, true, true, false, true, true}}
        };
    }
}
